package com.transfiguro.converters;

import ch.qos.logback.core.StopWatch;
import com.transfiguro.datamodel.csmodels.Usings;
import com.transfiguro.datamodel.javamodels.Imports;
import com.transfiguro.exceptions.ConversionFailedException;
import com.transfiguro.utilities.FileUtilities;
import com.transfiguro.utilities.MappingXMLParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;

import java.io.File;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;

/**
 * An implementation of {@link Converter}. This class provides methods to convert
 * a given {@link Imports} to {@link Usings}
 */
public class ImportsConverter implements Converter {
    private final Logger logger = LoggerFactory.getLogger(ImportsConverter.class);

    private Usings usings;
    private Imports imports;
    private File importsXMLMapping;
    private static MappingXMLParser xmlParser;
    private static final String UNMAPPED_IMPORT = "<<<Unmapped Import>>>";

    /**
     * Constructor
     *
     * @param imports  The imports to be converted
     */
    public ImportsConverter(final Imports imports) {
        this.imports = imports;
        usings = new Usings();
        init();
    }

    /**
     * Initializer for various private variables
     */
    public void init() {
        final ClassPathResource resource = new ClassPathResource("mappingxmls/ImportsMapping.xml");
        final InputStream stream = ClassLoader.getSystemResourceAsStream("mappingxmls/ImportsMapping.xml");
        final File tempFile = new File(".", "ImportsMapping.xml");
        FileUtilities.writeTempFile(stream, tempFile);
        importsXMLMapping = tempFile;
        xmlParser = new MappingXMLParser(importsXMLMapping);
    }

    /**
     * This method converts the given <code>Imports</code> to <code>Usings</code>
     *
     * @return  <tt>True</tt> if conversion was successful
     * @throws ConversionFailedException  If there was a problem in conversion
     */
    public boolean convert() throws ConversionFailedException {
        boolean result = true;
        Set<String> usingStrings = new HashSet<String>();
        final StopWatch stopWatch = new StopWatch("ImportsConversionTimer");
        for (final String importString : imports.getImports()) {
            if (xmlParser.requiresConversion("import", importString)) {
                usingStrings.add(xmlParser.getTo("import", importString));
            } else {
                usingStrings.add(importString + UNMAPPED_IMPORT);
            }
        }
        usings.setUsings(usingStrings);
        stopWatch.stop();
        usings.setConversionTime(stopWatch.getResultInSeconds());
        return result;
    }

    /**
     * Getter for usings
     *
     * @return  The <code>Usings</code> instance created by converting
     *         the given <code>Imports</code>
     */
    public Usings getUsings() {
        return usings;
    }

}
